home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / file-tra / ftp-rl.taz / ftp-rl / ftp / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-07  |  9.9 KB  |  541 lines

  1. /*
  2.  * Copyright (c) 1985, 1989 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that: (1) source distributions retain this entire copyright
  7.  * notice and comment, and (2) distributions including binaries display
  8.  * the following acknowledgement:  ``This product includes software
  9.  * developed by the University of California, Berkeley and its contributors''
  10.  * in the documentation or other materials provided with the distribution
  11.  * and in all advertising materials mentioning features or use of this
  12.  * software. Neither the name of the University nor the names of its
  13.  * contributors may be used to endorse or promote products derived
  14.  * from this software without specific prior written permission.
  15.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  16.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  17.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18.  */
  19.  
  20. #ifndef lint
  21. char copyright[] =
  22. "@(#) Copyright (c) 1985, 1989 Regents of the University of California.\n\
  23.  All rights reserved.\n";
  24. #endif /* not lint */
  25.  
  26. #ifndef lint
  27. static char sccsid[] = "@(#)main.c    5.16 (Berkeley) 6/1/90";
  28. #endif /* not lint */
  29.  
  30. /*
  31.  * This version of FTP has been modified to interface with the GNU
  32.  * readline and history libraries.  The following RCS information is
  33.  * provided for interested readers.   - wollman@emily.uvm.edu
  34.  */
  35.  
  36. #ifndef lint
  37. static char rcsid[] = "$Header: /home/emily1/others/wollman/src/ftp/RCS/main.c,v 5.19 90/11/19 00:21:25 wollman Exp Locker: wollman $";
  38. #endif
  39. /*
  40.  * $Log:    main.c,v $
  41.  * Revision 5.19  90/11/19  00:21:25  wollman
  42.  * Corrected small bug reading input...
  43.  * 
  44.  * Revision 5.18  90/11/19  00:05:44  wollman
  45.  * Added initial support for readline.  There is a disgusting hack in here.
  46.  * No support for completion as yet, but we do have history.
  47.  * 
  48.  * Revision 5.17  90/11/18  23:46:24  wollman
  49.  * Added information about nature and purpose of modifications for future
  50.  * reference.
  51.  * 
  52.  */
  53.  
  54. /*
  55.  * FTP User Program -- Command Interface.
  56.  */
  57. #include "ftp_var.h"
  58. #include <sys/socket.h>
  59. #include <sys/ioctl.h>
  60. #include <sys/types.h>
  61.  
  62. #include <arpa/ftp.h>
  63.  
  64. #include <signal.h>
  65. #include <stdio.h>
  66. #include <errno.h>
  67. #include <ctype.h>
  68. #include <netdb.h>
  69. #include <pwd.h>
  70. #include <readline/readline.h>
  71. #include <readline/history.h>
  72.  
  73. uid_t    getuid();
  74. sig_t    intr();
  75. sig_t    lostpeer();
  76. extern    char *home;
  77. char    *getlogin();
  78.  
  79. main(argc, argv)
  80.     char *argv[];
  81. {
  82.     register char *cp;
  83.     int top;
  84.     struct passwd *pw = NULL;
  85.     char homedir[MAXPATHLEN];
  86.  
  87.     sp = getservbyname("ftp", "tcp");
  88.     if (sp == 0) {
  89.         fprintf(stderr, "ftp: ftp/tcp: unknown service\n");
  90.         exit(1);
  91.     }
  92.     doglob = 1;
  93.     interactive = 1;
  94.     autologin = 1;
  95.     argc--, argv++;
  96.     while (argc > 0 && **argv == '-') {
  97.         for (cp = *argv + 1; *cp; cp++)
  98.             switch (*cp) {
  99.  
  100.             case 'd':
  101.                 options |= SO_DEBUG;
  102.                 debug++;
  103.                 break;
  104.             
  105.             case 'v':
  106.                 verbose++;
  107.                 break;
  108.  
  109.             case 't':
  110.                 trace++;
  111.                 break;
  112.  
  113.             case 'i':
  114.                 interactive = 0;
  115.                 break;
  116.  
  117.             case 'n':
  118.                 autologin = 0;
  119.                 break;
  120.  
  121.             case 'g':
  122.                 doglob = 0;
  123.                 break;
  124.  
  125.             default:
  126.                 fprintf(stdout,
  127.                   "ftp: %c: unknown option\n", *cp);
  128.                 exit(1);
  129.             }
  130.         argc--, argv++;
  131.     }
  132.     fromatty = isatty(fileno(stdin));
  133.     if (fromatty)
  134.         verbose++;
  135.     cpend = 0;    /* no pending replies */
  136.     proxy = 0;    /* proxy not active */
  137.     crflag = 1;    /* strip c.r. on ascii gets */
  138.     sendport = -1;    /* not using ports */
  139.     /*
  140.      * Set up the home directory in case we're globbing.
  141.      */
  142.     cp = getlogin();
  143.     if (cp != NULL) {
  144.         pw = getpwnam(cp);
  145.     }
  146.     if (pw == NULL)
  147.         pw = getpwuid(getuid());
  148.     if (pw != NULL) {
  149.         home = homedir;
  150.         (void) strcpy(home, pw->pw_dir);
  151.     }
  152.     if (argc > 0) {
  153.         if (setjmp(toplevel))
  154.             exit(0);
  155.         (void) signal(SIGINT, intr);
  156.         (void) signal(SIGPIPE, lostpeer);
  157.         setpeer(argc + 1, argv - 1);
  158.     }
  159.     top = setjmp(toplevel) == 0;
  160.     if (top) {
  161.         (void) signal(SIGINT, intr);
  162.         (void) signal(SIGPIPE, lostpeer);
  163.     }
  164.     for (;;) {
  165.         cmdscanner(top);
  166.         top = 1;
  167.     }
  168. }
  169.  
  170. sig_t
  171. intr()
  172. {
  173.  
  174.     longjmp(toplevel, 1);
  175. }
  176.  
  177. sig_t
  178. lostpeer()
  179. {
  180.     extern FILE *cout;
  181.     extern int data;
  182.  
  183.     if (connected) {
  184.         if (cout != NULL) {
  185.             (void) shutdown(fileno(cout), 1+1);
  186.             (void) fclose(cout);
  187.             cout = NULL;
  188.         }
  189.         if (data >= 0) {
  190.             (void) shutdown(data, 1+1);
  191.             (void) close(data);
  192.             data = -1;
  193.         }
  194.         connected = 0;
  195.     }
  196.     pswitch(1);
  197.     if (connected) {
  198.         if (cout != NULL) {
  199.             (void) shutdown(fileno(cout), 1+1);
  200.             (void) fclose(cout);
  201.             cout = NULL;
  202.         }
  203.         connected = 0;
  204.     }
  205.     proxflag = 0;
  206.     pswitch(0);
  207. }
  208.  
  209. /*char *
  210. tail(filename)
  211.     char *filename;
  212. {
  213.     register char *s;
  214.     
  215.     while (*filename) {
  216.         s = rindex(filename, '/');
  217.         if (s == NULL)
  218.             break;
  219.         if (s[1])
  220.             return (s + 1);
  221.         *s = '\0';
  222.     }
  223.     return (filename);
  224. }
  225. */
  226. /*
  227.  * Command parser.
  228.  */
  229. cmdscanner(top)
  230.     int top;
  231. {
  232.     register struct cmd *c;
  233.     struct cmd *getcmd();
  234.     extern int help();
  235.     char *lineread;
  236.  
  237.     if (!top)
  238.         (void) putchar('\n');
  239.     for (;;) {
  240. #ifdef notdef
  241.         if (fromatty) {
  242.             printf("ftp> ");
  243.             (void) fflush(stdout);
  244.         }
  245. #else
  246.         if (fromatty) {
  247.             lineread = readline("ftp> ");
  248.         }
  249. #endif
  250.         if (!fromatty) {
  251.             if (gets(line) == 0) {
  252.                 if (feof(stdin) || ferror(stdin))
  253.                   quit();
  254.                 break;
  255.             }
  256.         } else {
  257.             if (!lineread) {
  258.                 quit();
  259.                 break;
  260.             }
  261.             /*
  262.              * This is a really ugly hack forced upon us
  263.              * because of the fact that line[] is global and
  264.              * other functions depend on it.  If I find the
  265.              * time, I will fix this.
  266.              */
  267.             strcpy(line,lineread);
  268.             if(lineread[0]) add_history(lineread);
  269.             free(lineread);
  270.         }
  271.  
  272.         if (line[0] == 0)
  273.             break;
  274.         makeargv();
  275.         if (margc == 0) {
  276.             continue;
  277.         }
  278.         c = getcmd(margv[0]);
  279.         if (c == (struct cmd *)-1) {
  280.             printf("?Ambiguous command\n");
  281.             continue;
  282.         }
  283.         if (c == 0) {
  284.             printf("?Invalid command\n");
  285.             continue;
  286.         }
  287.         if (c->c_conn && !connected) {
  288.             printf ("Not connected.\n");
  289.             continue;
  290.         }
  291.         (*c->c_handler)(margc, margv);
  292.         if (bell && c->c_bell)
  293.             (void) putchar('\007');
  294.         if (c->c_handler != help)
  295.             break;
  296.     }
  297.     (void) signal(SIGINT, intr);
  298.     (void) signal(SIGPIPE, lostpeer);
  299. }
  300.  
  301. struct cmd *
  302. getcmd(name)
  303.     register char *name;
  304. {
  305.     extern struct cmd cmdtab[];
  306.     register char *p, *q;
  307.     register struct cmd *c, *found;
  308.     register int nmatches, longest;
  309.  
  310.     longest = 0;
  311.     nmatches = 0;
  312.     found = 0;
  313.     for (c = cmdtab; p = c->c_name; c++) {
  314.         for (q = name; *q == *p++; q++)
  315.             if (*q == 0)        /* exact match? */
  316.                 return (c);
  317.         if (!*q) {            /* the name was a prefix */
  318.             if (q - name > longest) {
  319.                 longest = q - name;
  320.                 nmatches = 1;
  321.                 found = c;
  322.             } else if (q - name == longest)
  323.                 nmatches++;
  324.         }
  325.     }
  326.     if (nmatches > 1)
  327.         return ((struct cmd *)-1);
  328.     return (found);
  329. }
  330.  
  331. /*
  332.  * Slice a string up into argc/argv.
  333.  */
  334.  
  335. int slrflag;
  336.  
  337. makeargv()
  338. {
  339.     char **argp;
  340.     char *slurpstring();
  341.  
  342.     margc = 0;
  343.     argp = margv;
  344.     stringbase = line;        /* scan from first of buffer */
  345.     argbase = argbuf;        /* store from first of buffer */
  346.     slrflag = 0;
  347.     while (*argp++ = slurpstring())
  348.         margc++;
  349. }
  350.  
  351. /*
  352.  * Parse string into argbuf;
  353.  * implemented with FSM to
  354.  * handle quoting and strings
  355.  */
  356. char *
  357. slurpstring()
  358. {
  359.     int got_one = 0;
  360.     register char *sb = stringbase;
  361.     register char *ap = argbase;
  362.     char *tmp = argbase;        /* will return this if token found */
  363.  
  364.     if (*sb == '!' || *sb == '$') {    /* recognize ! as a token for shell */
  365.         switch (slrflag) {    /* and $ as token for macro invoke */
  366.             case 0:
  367.                 slrflag++;
  368.                 stringbase++;
  369.                 return ((*sb == '!') ? "!" : "$");
  370.                 /* NOTREACHED */
  371.             case 1:
  372.                 slrflag++;
  373.                 altarg = stringbase;
  374.                 break;
  375.             default:
  376.                 break;
  377.         }
  378.     }
  379.  
  380. S0:
  381.     switch (*sb) {
  382.  
  383.     case '\0':
  384.         goto OUT;
  385.  
  386.     case ' ':
  387.     case '\t':
  388.         sb++; goto S0;
  389.  
  390.     default:
  391.         switch (slrflag) {
  392.             case 0:
  393.                 slrflag++;
  394.                 break;
  395.             case 1:
  396.                 slrflag++;
  397.                 altarg = sb;
  398.                 break;
  399.             default:
  400.                 break;
  401.         }
  402.         goto S1;
  403.     }
  404.  
  405. S1:
  406.     switch (*sb) {
  407.  
  408.     case ' ':
  409.     case '\t':
  410.     case '\0':
  411.         goto OUT;    /* end of token */
  412.  
  413.     case '\\':
  414.         sb++; goto S2;    /* slurp next character */
  415.  
  416.     case '"':
  417.         sb++; goto S3;    /* slurp quoted string */
  418.  
  419.     default:
  420.         *ap++ = *sb++;    /* add character to token */
  421.         got_one = 1;
  422.         goto S1;
  423.     }
  424.  
  425. S2:
  426.     switch (*sb) {
  427.  
  428.     case '\0':
  429.         goto OUT;
  430.  
  431.     default:
  432.         *ap++ = *sb++;
  433.         got_one = 1;
  434.         goto S1;
  435.     }
  436.  
  437. S3:
  438.     switch (*sb) {
  439.  
  440.     case '\0':
  441.         goto OUT;
  442.  
  443.     case '"':
  444.         sb++; goto S1;
  445.  
  446.     default:
  447.         *ap++ = *sb++;
  448.         got_one = 1;
  449.         goto S3;
  450.     }
  451.  
  452. OUT:
  453.     if (got_one)
  454.         *ap++ = '\0';
  455.     argbase = ap;            /* update storage pointer */
  456.     stringbase = sb;        /* update scan pointer */
  457.     if (got_one) {
  458.         return(tmp);
  459.     }
  460.     switch (slrflag) {
  461.         case 0:
  462.             slrflag++;
  463.             break;
  464.         case 1:
  465.             slrflag++;
  466.             altarg = (char *) 0;
  467.             break;
  468.         default:
  469.             break;
  470.     }
  471.     return((char *)0);
  472. }
  473.  
  474. #define HELPINDENT (sizeof ("directory"))
  475.  
  476. /*
  477.  * Help command.
  478.  * Call each command handler with argc == 0 and argv[0] == name.
  479.  */
  480. help(argc, argv)
  481.     int argc;
  482.     char *argv[];
  483. {
  484.     extern struct cmd cmdtab[];
  485.     register struct cmd *c;
  486.  
  487.     if (argc == 1) {
  488.         register int i, j, w, k;
  489.         int columns, width = 0, lines;
  490.         extern int NCMDS;
  491.  
  492.         printf("Commands may be abbreviated.  Commands are:\n\n");
  493.         for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
  494.             int len = strlen(c->c_name);
  495.  
  496.             if (len > width)
  497.                 width = len;
  498.         }
  499.         width = (width + 8) &~ 7;
  500.         columns = 80 / width;
  501.         if (columns == 0)
  502.             columns = 1;
  503.         lines = (NCMDS + columns - 1) / columns;
  504.         for (i = 0; i < lines; i++) {
  505.             for (j = 0; j < columns; j++) {
  506.                 c = cmdtab + j * lines + i;
  507.                 if (c->c_name && (!proxy || c->c_proxy)) {
  508.                     printf("%s", c->c_name);
  509.                 }
  510.                 else if (c->c_name) {
  511.                     for (k=0; k < strlen(c->c_name); k++) {
  512.                         (void) putchar(' ');
  513.                     }
  514.                 }
  515.                 if (c + lines >= &cmdtab[NCMDS]) {
  516.                     printf("\n");
  517.                     break;
  518.                 }
  519.                 w = strlen(c->c_name);
  520.                 while (w < width) {
  521.                     w = (w + 8) &~ 7;
  522.                     (void) putchar('\t');
  523.                 }
  524.             }
  525.         }
  526.         return;
  527.     }
  528.     while (--argc > 0) {
  529.         register char *arg;
  530.         arg = *++argv;
  531.         c = getcmd(arg);
  532.         if (c == (struct cmd *)-1)
  533.             printf("?Ambiguous help command %s\n", arg);
  534.         else if (c == (struct cmd *)0)
  535.             printf("?Invalid help command %s\n", arg);
  536.         else
  537.             printf("%-*s\t%s\n", HELPINDENT,
  538.                 c->c_name, c->c_help);
  539.     }
  540. }
  541.